<?php
namespace Application\controller;
use Application\model\BaseLoginModel;
use Cola\Controller;
use Cola\Request;


class BaseLoginController extends Controller
{

    /**
     * @var \Application\model\BaseLoginModel
     */
    protected $loginModel;

    /**
     * 构造方法的扩展
     */
    protected function _init()
    {

    }

    /**
     * 初始化返回的结构体
     * @return array
     */
    protected function initStruct()
    {
        return [
          'accountInfo' => [],
          'serverInfo' => [],
          'authCode' => '',
          'openId' => ''
        ];
    }

    /**
     * 初始化登录
     * @return BaseLoginModel
     */
    protected function initLogin()
    {
        /* @var BaseLoginModel $m */
        $m = $this->model('Login');
        $m->getLoginParams();

        return $this->loginModel = $m;
    }
    /**
     * 初始化超级登录
     * @return BaseLoginModel
     */
    protected function initSuperLogin($checkWhitelist = true,$m=null)
    {
        /* @var BaseLoginModel $m */
        !$m && $m = $this->model('Login');

        // 检测白名单
        if ($checkWhitelist) {
            $m->openId = CID.'-'.$m->openId;
            $whitelist = $this->isWhitelist($m->openId);
            $m->whitelist = $whitelist;
            // 非白名单直接返回
            if (!$whitelist) {
                return $this->loginModel = $m;
            }
        }

        $m->getSuperLoginParams();

        return $this->loginModel = $m;
    }

    /**
     *  获取玩家数据
     *  是否新玩家，新玩家则返回空，老玩家则返回最近登录的区服角色信息
     * @param $m
     * @return array
     */
    protected function getAccountInfo($m): array
    {

        $accountInfo = $this->model('Account')->initAccount($m);
        if ($accountInfo['status'] === '0') logfile('LoginModel', "account:{$m->account} has been banned");
        if (!isset($accountInfo['banTime'])) $accountInfo['banTime'] = 0;
        return $accountInfo;
    }

    protected function getSuperAccountInfo($m): array
    {
        $accountInfo = $this->model('Account')->getLastLoginAccount($m->account, true, $m->cid);
        if ($accountInfo) $accountInfo= $accountInfo[0];

        $this->initSuperServerMap($m);
        return $accountInfo;
    }

    private function initSuperServerMap($m)
    {
        $where = '';
        $where .= $m->getChannelServerMap($where, $m->cpid, $m->cid);
        $this->loginModel->serverWhere = $where;
    }

    protected function checkChannel($cid = '', $whitelist=0)
    {
        !$cid && $cid = realCID();
        // 白名单不限制
        $status = 1;
        if ($whitelist) return $status;
        // 获取渠道数据
        $channel = $this->model('Channel')->getChannelInfo($cid, false);
        if ($channel) {
            $status = $channel['status'];
        }
        return $status;
    }

    /**
     * 获取区服信息
     *    返回玩家最近登录的区服信息，如果玩家账号为空就返回随机推荐服务器信息, 最新开服
     * @param $accountInfo
     * @return array
     */
    protected function getServerInfo($accountInfo,$cid): array
    {
        $serverModel = $this->model('Server');
        // 受限于开服时间和显示时间
        $where = $this->loginModel->serverWhere;
        $ServerModel = $this->model('Server');
        $sids = $ServerModel->getSidsBySrid($where);
        //更换了渠道还是推荐服(有映射渠道
        //更换了大区还是推荐服
        if ($cid==$accountInfo['last_cid'] && isset($accountInfo['sid']) && !empty($accountInfo['sid']) && in_array($accountInfo['sid'],$sids)) {
            // 返回玩家最近登录的区服信息
            $serverInfo = $serverModel->getServerBySid($accountInfo['sid']);
            $sidLoad = "last login:{$accountInfo['sid']},srid:{$where}";
        } else {
            // 返回最新推荐的区服
            $count = $serverModel->db->count($where." and is_recommend=1", 'ops_servers');
            // 如果没有推荐服，默认选择开服时间最近的服
            if($count === 0){
                $serverInfo = $serverModel->getServerInfo($where);
                if(empty($serverInfo)){
                    logfile('LoginModel', "servers empty");
                    return [];
                }
                $sidLoad = "last login:{$serverInfo['sid']} recommend:0";
            } else {
                // 返回推荐列表中随机的一个服
                $serverInfo = $serverModel->getRecommendServer($where);
                $sidLoad = "last login:{$serverInfo['sid']} recommend:1";
            }
        }
        $server = $this->loginModel->serverStruct(
            $serverInfo,
            $this->loginModel->actorStruct($accountInfo)
        );
        logfile('LoginModel', "sid load:{$sidLoad}");
        return $server;
    }

    public function getSuperServerInfo($accountInfo): array
    {
        $serverModel = $this->model('Server');
        // 返回玩家最近登录的区服信息
        $serverInfo = $serverModel->getServerBySid($accountInfo['sid']);
        $sidLoad = "last login:{$accountInfo['sid']}";

        // 获取该平台所有区服
        $server = $this->loginModel->serverStruct(
            $serverInfo,
            $this->loginModel->actorStruct($accountInfo)
        );
        logfile('LoginModel', "sid load:{$sidLoad}");
        return $server;
    }

    /**
     * 生成一个随机的密码
     * @param $account
     * @param $whitelist
     * @return string
     */
    protected function generateCode($account, $whitelist)
    {
        /* @var BaseLoginModel $m */
        $m = $this->model('Login');
        $code = $m->generateVerifyCode($account, $whitelist);
        return $code;
    }

    /**
     * 生成一个账号srid
     * @param $account
     * @param $whitelist
     * @return string
     */
    protected function setAccountSrid($account, $whitelist, $srid)
    {
        /* @var BaseLoginModel $m */
        $m = $this->model('Login');
        $m->setAccountSridRedis($account, $whitelist, $srid);
    }

    /**
     * 是否白名单
     * @param $account
     * @return int
     */
    protected function isWhitelist($account, $device='')
    {
        $res = $this->model('Whitelist')->getByAccount($account, $device);
        return $res ? 1 : 0;
    }

    protected function checkDevice($deviceCode)
    {
        $res = $this->model('Whitelist')->getPassDevice($deviceCode);
        if (!$res) logfile('LoginModel', "device: {$deviceCode} false");
        // 如果通过的设备返回
        return $res ? 1 : 0;
    }

    protected function checkIP($accountInfo, $whitelist)
    {
        // 先判断是否已经被封号
        if ($accountInfo['status'] === '0') return $accountInfo;

        $ip = ip();
        if ($whitelist === 0) {
            // 检测ip是否被封禁
            $res = $this->model('Ban')->checkBanIp();
            if ($res) {
                $accountInfo['status'] = '0';
                $banTime = 0;
                // 获取封禁时间
                $info = $this->model('Ban')->getBanTimeByIp($ip);
                if ($info) $banTime = strtotime($info['ban_dt']) + ($info['ban_time']*60);
                $accountInfo['banTime'] = $banTime;
            }
        }
        return $accountInfo;
    }

    /**
     * 获取最近登录区服列表
     * @param $account
     * @param $cpid
     * @param null $m
     * @return array
     */
    public function getLastLoginServers($account, $cpid, $m=null): array
    {
        /* @var BaseLoginModel $m */
        if(!$m){
            $m = $this->model('Login');
            $m->account = $account;
            if (empty($cpid)) $cpid = realGAME_ID();
            $m->cpid = $cpid;
            $this->loginModel = $m;
            // 初始化区服条件
            $this->initServerMap();
        }




        // 通过cid和openid获取最近登录列表
        $accountInfo = $this->model('Account')->getLastLoginAccount($account);
        $data = [];
        $datas = [];
        if ($accountInfo) {
            $ServerModel = $this->model('Server');
            // 获取出符合的最后一条
            foreach ($accountInfo as $a) {
                // 受限于开服时间和显示时间
                $where = preg_replace('/and$/', '', trim($this->loginModel->serverWhere))." and sid = {$a['sid']}";
                // 通过区服Id查区服信息

                $server = $ServerModel->getServerInfo($where);

                // 显示时间
                if ($server) {
                    $tdata = ['sid' => $a['sid']];
                    //当前渠道的默认在前面
                    if($a['last_cid']==$m->cpid){
                        $datas = array_merge([$tdata], $datas);
                        break;
                    }else{
                        $datas[] = $tdata;
                    }
                }
            }
            $datas && $data = current($datas);
        }

        return [$data, $accountInfo];
    }

    /**
     * 首先根据子包的指定大区找区服列表，其次根据渠道所属大区找区服列表
     * @param $accountInfo
     * @param $cpid
     * @return array
     */
    protected function getServers($accountInfo, $cpid): array
    {
        $accounts = $sgids = [];
        if ($accountInfo){
            foreach ($accountInfo as $item) {
                $accounts[$item['sid']] = $item;
            }
        }

        $ServerModel = $this->model('Server');
        // 通过大区id获取区服数据
        // 受限于开服时间和显示时间
        $where = preg_replace('/and$/', '', trim($this->loginModel->serverWhere));
//        $where = 'is_display=1';
        $servers = $ServerModel->getServers($where);
        if ($servers){
            foreach ($servers as &$server) {
                $actor = [];
                if (isset($accounts[$server['sid']])){
                    $actor = $this->loginModel->actorStruct($accounts[$server['sid']]);
                }
                $sgids[] = $server['sgid'];
                $server = $this->loginModel->serverStruct($server, $actor);
            }
        }
        return [$sgids, $servers];
    }

    /**
     * 获取渠道包信息
     * @return array
     */
    public function getChannelPackageInfo()
    {
        $ChannelModel = $this->model('Channel');
        $channel = $this->get('channel');
        $cpid = $channel ?? GAME_ID;
        $info = $ChannelModel->getChannelPackageInfoByCpid($cpid);
        return $this->getChannelStruct($info);
    }

    public function getChannelPackageInfoByType($type)
    {
        $content = '';
        if (in_array($type, ['agreement', 'privacy']) ) {
            $channel = $this->get('channel');
            $ChannelModel = $this->model('Channel');
            $cpid = $channel ?? GAME_ID;
            $info = $ChannelModel->getChannelPackageInfoByCpid($cpid);

            $ConfigModel = $this->model('Config');
            if ($type === 'agreement') $content = isset($info['agreement']) && !empty($info['agreement']) ? $info['agreement'] : $ConfigModel->getInfoByKey('default_agreement', 'value');
            if ($type === 'privacy') $content = isset($info['privacy']) && !empty($info['privacy']) ? $info['privacy'] : $ConfigModel->getInfoByKey('default_privacy', 'value');
            $content = htmlToBBCode($content);
        }

        return ['content' => $content];
    }

    public function checkServer($openId, $sid)
    {
        // 获取缓存信息（白名单和大区）
        $loginModel = $this->model('Login');
        $values = $loginModel->getAccountRedis($openId);
        if (empty($values)){
            logfile('LoginModel', "no getAccountRedis--{$openId}:{$sid}");
            return false;
        }
        $whitelist = $values[0];
        // 检测区服id是否已开服或者是否合法
        if (!$whitelist) {
            if (!isset($values[1])){
                logfile('LoginModel', "error getAccountRedis--".var_export($values,true));
                return false;
            }
            $srid = explode(',', $values[1]);
            $server = $this->model('Server')->getServerInfo("sid={$sid}");
            if ($server && !empty($srid)) {
                if ( in_array($server['srid'], $srid)) {
                    // 加redis key sid-account
                    $code = $loginModel->generateVerifyCode($sid.'-'.$openId, $whitelist);
                    return $code;
                }
            }else{
                logfile('LoginModel', "error getAccountRedis--{$sid}--".var_export($values,true));
            }
            return false;
        } else {
            // 加redis key sid-account
            $code = $loginModel->generateVerifyCode($sid.'-'.$openId, $whitelist);
            return $code;
        }
    }

    private function getChannelStruct($data)
    {
        return [
          'isShowAgeTips' => $data['age_tips'] ?? '0',
          'copyright' => $data['copyright'] ?? '',
          'isShowAgreement' => $data['is_show_agreement'] ?? 0,
          'agreement' => isset($data['agreement']) && !empty($data['agreement']) ? '1' : '0',
          'privacy' => isset($data['privacy']) && !empty($data['privacy']) ? '1' : '0',
        ];
    }

    /**
     * 初始化区服列表的条件
     * @param $isWhitelist
     * @return void
     */
    public function initServerMap($isWhitelist=-1)
    {
        // 先检查白名单，白名单可以看到全部白名单区服
        if ($isWhitelist === -1){
            $deviceCode = $this->get('deviceCode');
            $isWhitelist = $this->isWhitelist($this->loginModel->account, $deviceCode);
        }
        $this->loginModel->initServerMap($isWhitelist, $this->loginModel->cpid);
    }

    public function logEnd($account, $msg)
    {
        logfile('LoginModel', "account:$account {$msg} \n           ################# login end ################");
    }


    // --------------- 分割线


    public function serverlist()
    {
    }

    /**
     * 游戏页
     */
    public function index()
    {

    }

    public function login()
    {
    }

    public function __get($name = '')
    {
        if (in_array($name, ['view', 'request', 'response', 'config'])) {
            return parent::__get($name);
        } // 实例化一个模型类
        elseif ('Model' === substr($name, -5)) {
            return $this->$name = $this->model(substr($name, 0, -5));
        }
        // 从$_GET或$_POST中取值
        return $this->$name = $this->get($name);
    }

    protected function redirect($url, $code = 302)
    {
        if(Request::isAjax())
        {
            // 添加X-FORWARDED-FOR, 防止在下一个页面获取不到真实的ip
            exit(curl($url, '', 1, [
                'X-FORWARDED-FOR: ' . ip()
            ]));
        }
        else
        {
            $this->response->redirect($url, $code);
        }
    }

}
